home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 February
/
EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso
/
earcd
/
patches
/
csfix.lha
/
csfix
/
Source
/
csfix.c
next >
Wrap
C/C++ Source or Header
|
1995-01-03
|
8KB
|
267 lines
/* csfix.c (c) Frank Meijer, 1995.
|
| PURPOSE:
| Allow ComicSetter to run under OS 3.0.
|
| HISTORY:
| 950103: Completed version 1.0.
| 950101: Works fine. To be done: install/remove,
| workbench launch and get rid of debugging.
| 941231: Fix bug in mem.asm (saving register A6).
| 941229: Identify by screen title, not by task name.
| 941226: Intercept calls to AllocMem() and FreeMem().
|
| SYMPTOM:
| The CS display would get scrambled on a SAVE (not always,
| but almost). After that, quitting from CS would cause a guru.
|
| DIAGNOSIS:
| Before a SAVE, CS reduces the screen depth to 1 plane.
| It restores the depth to 4 after the save is done.
| However, the backdrop window's BitMap does not get updated,
| so that if the plane memory allocated for planes 1..3 is not
| the same as before the SAVE, the window is out of sync with
| the screen.
| I assume this worked in OS 1.3 because there were no other
| allocations done during the SAVE, so that the memory was
| always allocated at the same location. However, under OS 3.0
| some memory is allocated during the SAVE.
|
| SOLUTION:
| Intercept the calls to FreeMem() and AllocMem().
| When CS frees the plane memory, don't really free it but
| store the addresses. When CS re-allocates plane memory,
| don't allocate it but return the old pointers.
| Note that this should not be done when all planes are freed,
| but only when planes 1..3 are freed.
|
| NOTES:
| - In order to verify that the request comes from CS, we don't
| check the task name but the active screen title. This has the
| advantage that changes from interlace to non-interlace are
| not even seen because the CS screen is closed at that time.
| Also, the screen title is independent from the program name
| so if the user renamed CS to someting else, it still works.
| This algorithm will fail if SAVE causes chunks of the
| same size as the screen planes to be allocated, but that does
| never seem to be the case.
| - Plane memory is either 16000 or 32000 bytes per plane.
| For non-interlaced: 640*200/8 = 16000. Double for interlaced.
|
*/
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/tasks.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include "defs.h"
#include "mem.h"
#include "info.h"
#define AllocMem_LIBOFF -198
#define FreeMem_LIBOFF -210
struct ExecBase *ExecBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
static APTR CSbuf[3] = { NULL, NULL, NULL };
static LONG CSsize = 0; /* plane memory size */
static int CSplane = 0; /* last freed plane + 1 */
static BOOL CSfreeall = FALSE; /* true if plane 0 is also being freed */
#define PROGNAME "CSfix v1.0"
#define PORTNAME "CSfix msgport"
#define INFO_DURATION 2 /* info window display time, in seconds */
static struct MsgPort *msgport;
/*----------------------------------------------------------------*/
__geta4 APTR myAllocMem( LONG size, LONG type )
{
APTR memaddr=NULL; /* return value */
struct Screen *screen;
if ( (CSplane > 0) && (size == CSsize) ) {
screen = IntuitionBase->ActiveScreen;
if ( screen && screen->Title &&
(memcmp(screen->Title, "ComicSetter", 11) == 0) ) {
if (CSplane == 3) {
/* this is the first allocation */
memaddr = CSbuf[0];
CSplane = 1;
} else {
/* not the first but plane memory has been saved */
memaddr = CSbuf[CSplane];
CSplane++;
if (CSplane == 3)
CSplane = 0; /* done */
}
#ifdef DEBUG
printf( "AllocMem( size=%ld, type=%08lx ) -> %08lx\n", size, type, memaddr );
#endif
}
}
if (memaddr == NULL)
memaddr = CALLrealAllocMem( size, type );
return( memaddr );
}
/*----------------------------------------------------------------*/
__geta4 void myFreeMem( APTR memaddr, LONG size )
{
BOOL really_free = TRUE;
struct Screen *screen;
struct BitMap *bitmap;
if ((size == 16000) || (size == 32000)) {
/* When changing between interlaced and non-interlaced, */
/* the active screen is the Workbench. We can ignore */
/* those cases because CS handles them correctly. */
/* The only case that concern is is the temporary plane */
/* de-allocation/allocation that is done during SAVE. */
screen = IntuitionBase->ActiveScreen;
if ( screen && screen->Title &&
(memcmp(screen->Title, "ComicSetter", 11) == 0) ) {
bitmap = &(screen->BitMap);
if (memaddr == bitmap->Planes[0])
CSfreeall = TRUE;
else {
if ( (NOT CSfreeall) && (memaddr == bitmap->Planes[CSplane+1]) ) {
#ifdef DEBUG
printf( "FreeMem( memaddr=%08lx size=%ld ) --> CSbuf[%d]\n",
memaddr, size, CSplane );
#endif
CSbuf[CSplane] = memaddr;
CSplane++;
CSsize = size;
really_free = FALSE;
}
CSfreeall = FALSE;
}
}
}
if (really_free)
CALLrealFreeMem( memaddr, size );
return;
}
/*----------------------------------------------------------------*/
main( int argc, char *argv[] )
{
enum { doInstall, doToggle, doQuit } action;
struct Message *msg;
/* Open libraries */
ExecBase = (struct ExecBase *) OpenLibrary( "exec.library", 0 );
if (ExecBase == NULL) goto End;
IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0);
if (IntuitionBase == NULL) goto End;
/* Get requested action from command line parameter */
action = doToggle;
if (argc > 1) {
if (STREQ( argv[1], "install" ))
action = doInstall;
else if (STREQ( argv[1], "quit" ))
action = doQuit;
else {
info_show( NULL, FALSE, PROGNAME, "invoked with invalid option!", INFO_DURATION );
goto End;
}
}
/* See if there's already a copy of me running */
msgport = (struct MsgPort *) FindPort( PORTNAME );
/* If we should toggle, determine which way */
if (action == doToggle)
if (msgport == NULL)
action = doInstall;
else
action = doQuit;
/* Perform the requested action */
if (action == doQuit) {
/* quit: send a message to the port of the copy of myself */
if (msgport != NULL) {
msg = (struct Message *) AllocMem( sizeof(*msg), MEMF_PUBLIC );
if (msg == NULL) goto End;
msg->mn_Node.ln_Type = NT_MESSAGE;
PutMsg( msgport, msg );
}
}
else { /* doInstall */
/* Cannot install twice */
if (msgport != NULL) {
info_show( NULL, FALSE, PROGNAME, "is already installed!", INFO_DURATION );
goto End;
}
/* Create the message port */
msgport = (struct Msgport *) CreatePort( PORTNAME, 0 );
if (msgport == NULL) goto End;
/* Intercept calls to AllocMem */
realAllocMem = (void *) SetFunction( ExecBase, AllocMem_LIBOFF, CALLmyAllocMem );
if (realAllocMem == NULL) goto End;
/* Intercept calls to FreeMem */
realFreeMem = (void *) SetFunction( ExecBase, FreeMem_LIBOFF, CALLmyFreeMem );
if (realFreeMem == NULL) goto End;
/* Tell the user */
info_show( NULL, FALSE, PROGNAME, "has been installed", INFO_DURATION );
/* Wait for a message */
WaitPort( msgport );
/* Delete the message */
while( msg = (struct Message *)GetMsg(msgport) )
FreeMem( msg, sizeof(msg) );
/* Delete the message port */
DeletePort( msgport );
/* Tell the user */
info_show( NULL, FALSE, PROGNAME, "has been removed", INFO_DURATION );
}
End:
/* Restore original vectors */
if (realAllocMem != NULL)
SetFunction( ExecBase, AllocMem_LIBOFF, realAllocMem );
if (realFreeMem != NULL)
SetFunction( ExecBase, FreeMem_LIBOFF, realFreeMem );
/* Close the libraries */
if (ExecBase != NULL)
CloseLibrary( ExecBase );
if (IntuitionBase != NULL)
CloseLibrary( IntuitionBase );
return( 0 );
}
/*----------------------------------------------------------------*/
int wbmain() /* When invoked from Workbench */
{
/* Call the main program as if we were launched from CLI */
main( 0, NULL );
return( 0 );
}